#include "mystdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>

MY_FILE* my_fopen(const char *path, const char *mode)
{
	// 1.确定文件打开类型
	int flag = 0;
	if(strcmp(mode, "w") == 0) flag |= (O_CREAT | O_WRONLY | O_TRUNC);
	else if(strcmp(mode, "a") == 0) flag |= (O_CREAT | O_WRONLY | O_APPEND);
	else if(strcmp(mode, "r") == 0) flag |= O_RDONLY;
	else{
		// other statue...
		// w+, a+, r+...
	}
	
	// 2.打开文件
	int _mode = 0666;
	int fd = 0;
	if(flag & O_CREAT) fd = open(path, flag, _mode); // 文件不存在
	else fd = open(path, flag); // 文件已存在
	if(fd < 0) return NULL;
	
	// 3.创建文件结构体
	MY_FILE* mf = (MY_FILE*)malloc(sizeof(MY_FILE));
	if(mf == NULL)
	{
		close(fd);
		return NULL;
	}
	memset(mf->buff, '\0', sizeof(mf->buff));

	// 4.赋值
	mf->fd = fd;
	mf->flag = BUFF_LINE;
	mf->cur = 0;

	// 5.返回
	return mf;
}
size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, MY_FILE *fp)
{
	// 1.缓冲区满
	if(fp->cur == LEN) my_fflush(fp);
	
	// 2.拷贝内容
	int write_sz = 0;
	int user_size = size * nmemb;
	if(LEN - fp->cur > user_size)
	{
		memcpy(fp->buff + fp->cur, ptr, user_size);
		fp->cur += user_size;
		write_sz = user_size;
	}
	else
	{
		memcpy(fp->buff + fp->cur, ptr, LEN-fp->cur);
		fp->cur = LEN;
		write_sz = LEN-fp->cur;
	}
	
	// 3.刷新方式
	if(fp->flag & BUFF_ALL) // 全刷新
	{
		if(fp->cur == LEN)
	  	my_fflush(fp);
	}
	else if(fp->flag & BUFF_LINE) // 行刷新
	{
		if(fp->buff[fp->cur-1] == '\n')
		my_fflush(fp);
	}
	else // 无缓存刷新
	{
		my_fflush(fp);
	}
	return write_sz;
}
int my_fclose(MY_FILE *fp)
{
	assert(fp);
	// 1.刷新缓冲区
	if(fp->cur > 0) my_fflush(fp);
	// 2.关闭文件
	close(fp->fd);
	// 3.释放file
	free(fp);
	fp = NULL;
	return 0;
}
int my_fflush(MY_FILE *fp)
{
	assert(fp);
	write(fp->fd, fp->buff, fp->cur);
	fp->cur = 0;
	// （内核态）强制刷新
	fsync(fp->fd);
	return 0;
}
